package com.wu.serviceImpl.sys;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.wu.base.ApiResponse;
import com.wu.base.ResultUtils;
import com.wu.entity.sys.SDepartmentDo;
import com.wu.entity.sys.SUserDo;
import com.wu.enums.SystemEnum;
import com.wu.enums.field.FlagEnum;
import com.wu.mapper.SDepartmentMapper;
import com.wu.mapper.SUserMapper;
import com.wu.pojo.reqeust.CommonIdRequest;
import com.wu.pojo.reqeust.CommonIdStatusRequest;
import com.wu.pojo.reqeust.sys.DepartmentEditRequest;
import com.wu.pojo.reqeust.sys.DepartmentListRequest;
import com.wu.pojo.reqeust.sys.DepartmentSaveRequest;
import com.wu.pojo.reqeust.sys.DepartmentTreeListRequest;
import com.wu.pojo.response.CommonIdNameResponse;
import com.wu.pojo.response.sys.DepartmentListResponse;
import com.wu.pojo.response.sys.DepartmentTreeUserListResponse;
import com.wu.service.sys.SDepartmentService;
import com.wu.util.DozerUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * 部门表(SDepartment)表服务实现类
 *
 * @since 2020-12-29 13:20:25
 */
@Service("sDepartmentService")
public class SDepartmentServiceImpl extends ServiceImpl<SDepartmentMapper, SDepartmentDo> implements SDepartmentService {
    @Resource
    private SDepartmentMapper departmentMapper;
    @Resource
    private SUserMapper sUserMapper;

    @Override
    public ApiResponse treeList(DepartmentTreeListRequest request) {
        Long departmentId = null == request.getId() ? request.getCurrentDepartId() : request.getId();
        SDepartmentDo sDepartmentDo = departmentMapper.queryById(departmentId);
        if (null == sDepartmentDo || FlagEnum.DELETE.getCode().equals(sDepartmentDo.getFlag())) {
            return ResultUtils.setError(SystemEnum.DATA_NOT_EXIST);
        }
        return ResultUtils.setOk(subTreeIdNames(Lists.newArrayList(departmentId)));
    }

    @Override
    public ApiResponse list(DepartmentListRequest request) {
        List<Long> longs = subIds(Lists.newArrayList(request.getCurrentDepartId()), Lists.newArrayList());
        longs.add(request.getCurrentDepartId());

        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .in("id", longs)
                .like(StringUtils.isNotBlank(request.getName()), "name", request.getName())
                .orderByDesc("id");
        List<SDepartmentDo> sDepartmentDos = departmentMapper.selectList(queryWrapper);
        List<DepartmentListResponse> departmentListResponses = new ArrayList<>();
        for (SDepartmentDo sDepartmentDo : sDepartmentDos) {
            DepartmentListResponse departmentListResponse = new DepartmentListResponse();
            departmentListResponse.setId(sDepartmentDo.getId());
            departmentListResponse.setName(sDepartmentDo.getName());
            departmentListResponse.setNumber(countDepartmentUser(sDepartmentDo.getId()));
            departmentListResponse.setParentId(sDepartmentDo.getParentId());
            departmentListResponses.add(departmentListResponse);
        }
        return ResultUtils.setOk(departmentListResponses, new PageInfo<>(sDepartmentDos));
    }

    @Override
    public ApiResponse optionList(DepartmentTreeListRequest request) {
        Long departmentId = null == request.getId() ? request.getCurrentDepartId() : request.getId();
        List<Long> longs = subIds(Lists.newArrayList(departmentId), Lists.newArrayList());
        longs.add(request.getCurrentDepartId());
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .in("id", longs)
                .orderByDesc("id");
        List<SDepartmentDo> sDepartmentDos = departmentMapper.selectList(queryWrapper);
        List<DepartmentListResponse> departmentListResponses = DozerUtil.mapList(sDepartmentDos, DepartmentListResponse.class);
        return ResultUtils.setOk(departmentListResponses);
    }

    @Override
    public ApiResponse save(DepartmentSaveRequest request) {

        QueryWrapper<SDepartmentDo> queryCount = new QueryWrapper<>();
        queryCount.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("name", request.getName());
        Integer selectCount = departmentMapper.selectCount(queryCount);
        if (selectCount > 0) {
            return ResultUtils.setError("部门名称已存在");
        }

        SDepartmentDo departmentDo = new SDepartmentDo();
        if (null != request.getParentId()) {
            QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                    .eq("id", request.getParentId());
            SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
            if (null == sDepartmentDo) {
                return ResultUtils.setError(SystemEnum.DATA_NOT_EXIST);
            }
            departmentDo.setLevel(sDepartmentDo.getLevel() + 1);
            departmentDo.setParentId(sDepartmentDo.getId());
        }
        departmentDo.setCreater(request.getCurrentUserId());
        departmentDo.setName(request.getName());
        departmentMapper.insert(departmentDo);
        return ResultUtils.setOk();
    }

    @Override
    public ApiResponse edit(DepartmentEditRequest request) {
        QueryWrapper<SDepartmentDo> queryCount = new QueryWrapper<>();
        queryCount.eq("flag", FlagEnum.NORMAL.getCode())
                .ne("id", request.getId())
                .eq("name", request.getName());
        Integer selectCount = departmentMapper.selectCount(queryCount);
        if (selectCount > 0) {
            return ResultUtils.setError("部门名称已存在");
        }
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("id", request.getId());
        SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
        if (null == sDepartmentDo) {
            return ResultUtils.setError(SystemEnum.DATA_NOT_EXIST);
        }
        sDepartmentDo.setModifier(request.getCurrentUserId());
        sDepartmentDo.setName(request.getName());
        sDepartmentDo.setModifyTime(new Date());
        int updateById = departmentMapper.updateById(sDepartmentDo);
        if (updateById < 1) {
            return ResultUtils.setError(SystemEnum.FAILED);
        }
        return ResultUtils.setOk();
    }

    @Override
    public ApiResponse delete(CommonIdRequest request) {
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("id", request.getId());
        SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
        if (null == sDepartmentDo) {
            return ResultUtils.setError(SystemEnum.DATA_NOT_EXIST);
        }
        if (sDepartmentDo.getParentId() == 0) {
            return ResultUtils.setError("此部门不可删除");
        }
        QueryWrapper<SDepartmentDo> querySubCount = new QueryWrapper<>();
        querySubCount.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("parent_id", request.getId());
        int selectCount = departmentMapper.selectCount(querySubCount);
        if (selectCount > 0) {
            return ResultUtils.setError("此部门下有子部门，不可删除");
        }
        if (countDepartmentUser(request.getId()) > 0) {
            return ResultUtils.setError("部门正在使用，不可删除");
        }
        sDepartmentDo.setModifier(request.getCurrentUserId());
        sDepartmentDo.setFlag(FlagEnum.DELETE.getCode());
        sDepartmentDo.setModifyTime(new Date());
        int updateById = departmentMapper.updateById(sDepartmentDo);
        if (updateById < 1) {
            return ResultUtils.setError(SystemEnum.FAILED);
        }
        return ResultUtils.setOk();
    }

    @Override
    public ApiResponse onOrOff(CommonIdStatusRequest request) {
        return null;
    }

    @Override
    public ApiResponse getById(CommonIdRequest request) {
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("id", request.getId());
        SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
        if (null == sDepartmentDo) {
            return ResultUtils.setError(SystemEnum.DATA_NOT_EXIST);
        }
        DepartmentListResponse map = DozerUtil.map(sDepartmentDo, DepartmentListResponse.class);
        map.setNumber(countDepartmentUser(map.getId()));
        //map.setSubList(subTreeIdNames(Lists.newArrayList(map.getId())));
        return ResultUtils.setOk(map);
    }

    @Override
    public ApiResponse treeAndUser(DepartmentTreeListRequest request) {
        Long departmentId = null == request.getId() ? request.getCurrentDepartId() : request.getId();
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("id", departmentId);
        SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
        if (null == sDepartmentDo) {
            return ResultUtils.setError(SystemEnum.DATA_NOT_EXIST);
        }
        List<DepartmentTreeUserListResponse> departmentTreeUserListResponses = subTreeUsers(Lists.newArrayList(departmentId));
        return ResultUtils.setOk(departmentTreeUserListResponses);
    }

    @Override
    public Long getDepartmentParentIdById(Long id) {

        return null;
    }

    @Override
    public List<Long> getDepartmentSubIdsByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Lists.newArrayList();
        }
        return subIds(ids, Lists.newArrayList());
    }

    @Override
    public List<Long> getDepartmentConnectionById(Long id) {
        if (null == id || 0 == id) {
            return Lists.newArrayList();
        }
        List<Long> longs = subIds(Lists.newArrayList(id), null);
        longs.add(id);
        longs.addAll(parentIdsById(id, null));
        longs.removeAll(Collections.singleton(null));
        return longs;
    }

    @Override
    public List<SDepartmentDo> getDepartmentSonsById(Long id) {
        if (null == id || 0 == id) {
            return Lists.newArrayList();
        }
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("parent_id", id);
        List<SDepartmentDo> departmentDos = departmentMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(departmentDos)) {
            departmentDos = Lists.newArrayList();
        }
        QueryWrapper<SDepartmentDo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("id", id);
        SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper1);
        if (null != sDepartmentDo) {
            departmentDos.add(sDepartmentDo);
        }
        return departmentDos;
    }

    /**
     * 部门下的子部门
     *
     * @param ids
     * @param resultIds
     * @return
     */
    private List<Long> subIds(List<Long> ids, List<Long> resultIds) {
        if (CollectionUtils.isEmpty(resultIds)) {
            resultIds = new ArrayList<>();
        }
        QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .in("parent_id", ids);
        List<SDepartmentDo> sDepartmentDos = departmentMapper.selectList(queryWrapper);
        List<Long> current = sDepartmentDos.stream().map(SDepartmentDo::getId).collect(toList());
        if (CollectionUtils.isEmpty(current)) {
            return resultIds;
        }
        resultIds.addAll(current);
        return subIds(current, resultIds);
    }

    /**
     * 部门树
     *
     * @param ids
     * @return
     */
    private List<DepartmentListResponse> subTreeIdNames(List<Long> ids) {
        List<DepartmentListResponse> result = Lists.newArrayList();
        if (CollectionUtils.isEmpty(ids)) {
            return result;
        }

        for (Long id : ids) {
            DepartmentListResponse department = new DepartmentListResponse();
            QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                    .eq("id", id);
            SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
            if (null == sDepartmentDo) {
                continue;
            }
            if (sDepartmentDo.getParentId() == 0) {
                QueryWrapper<SUserDo> queryCount = new QueryWrapper<>();
                queryCount.eq("flag", FlagEnum.NORMAL.getCode());
                Integer selectCount = sUserMapper.selectCount(queryCount);
                department.setNumber(selectCount);
            } else {
                department.setNumber(countDepartmentUser(id));
            }
            department.setName(sDepartmentDo.getName());
            department.setId(sDepartmentDo.getId());
            department.setParentId(sDepartmentDo.getParentId());
            department.setLevel(sDepartmentDo.getLevel());
            QueryWrapper<SDepartmentDo> querySub = new QueryWrapper<>();
            querySub.eq("flag", FlagEnum.NORMAL.getCode())
                    .eq("parent_id", id);
            List<SDepartmentDo> sDepartmentDos = departmentMapper.selectList(querySub);
            department.setSubList(subTreeIdNames(sDepartmentDos.stream().map(SDepartmentDo::getId).collect(toList())));
            result.add(department);
        }
        return result;
    }

    private List<DepartmentTreeUserListResponse> subTreeUsers(List<Long> ids) {
        List<DepartmentTreeUserListResponse> result = Lists.newArrayList();
        if (CollectionUtils.isEmpty(ids)) {
            return result;
        }

        for (Long id : ids) {
            DepartmentTreeUserListResponse department = new DepartmentTreeUserListResponse();
            QueryWrapper<SDepartmentDo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                    .eq("id", id);
            SDepartmentDo sDepartmentDo = departmentMapper.selectOne(queryWrapper);
            if (null == sDepartmentDo) {
                continue;
            }
            department.setName(sDepartmentDo.getName());
            department.setId(sDepartmentDo.getId());
            List<CommonIdNameResponse> departmentUser = sUserMapper.getUserByDepartmentId(id);
            department.setNumber(departmentUser.size());
            department.setUserList(departmentUser);
            QueryWrapper<SDepartmentDo> querySub = new QueryWrapper<>();
            querySub.eq("flag", FlagEnum.NORMAL.getCode())
                    .eq("parent_id", id);
            List<SDepartmentDo> sDepartmentDos = departmentMapper.selectList(querySub);
            department.setSubList(subTreeUsers(sDepartmentDos.stream().map(SDepartmentDo::getId).collect(toList())));
            result.add(department);
        }
        return result;
    }


    private int countDepartmentUser(Long departmentId) {
        QueryWrapper<SUserDo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flag", FlagEnum.NORMAL.getCode())
                .eq("department_id", departmentId);
        return sUserMapper.selectCount(queryWrapper);
    }

    /**
     * 倒查部门树数据  根据子、孙 查顶级
     *
     * @param currentList 当前数据
     * @param result      所有数据
     * @return
     */
    private List<Long> parentIdsById(Long currentList, List<Long> result) {
        if (CollectionUtils.isEmpty(result)) {
            result = Lists.newArrayList();
        }
        if (null == currentList || 0 == currentList) {
            return result;
        }
        SDepartmentDo sDepartmentDo = departmentMapper.selectById(currentList);
        if (null == sDepartmentDo || FlagEnum.DELETE.getCode().equals(sDepartmentDo.getFlag())) {
            return result;
        }
        if (0 != sDepartmentDo.getParentId()) {
            result.add(sDepartmentDo.getParentId());
        }
        return parentIdsById(sDepartmentDo.getParentId(), result);
    }

    /**
     * 倒查部门树数据  根据子、孙 查顶级
     *
     * @param currentList 当前数据，也是最低层数据
     * @param sourceLists 所有数据
     * @return
     */
    private List<DepartmentListResponse> subTreeBySource(List<DepartmentListResponse> currentList, List<DepartmentListResponse> sourceLists) {
        List<DepartmentListResponse> result = Lists.newArrayList();

        //当前对象的父类
        List<DepartmentListResponse> departmentRes = new ArrayList<>();
        for (DepartmentListResponse departmentDo : currentList) {
            DepartmentListResponse departmentListResponse = subTreeBySingle(departmentDo, sourceLists);
            if (null == departmentListResponse) {
                continue;
            }
            departmentRes.add(departmentListResponse);
        }
        departmentRes.removeAll(Collections.singleton(null));
        if (CollectionUtils.isEmpty(departmentRes)) {
            return currentList;
        }
        return subTreeBySource(departmentRes, sourceLists);
    }

    private DepartmentListResponse subTreeBySingle(DepartmentListResponse current, List<DepartmentListResponse> sourceLists) {
        DepartmentListResponse departmentDoe = null;
        if (CollectionUtils.isEmpty(sourceLists)) {
            return departmentDoe;
        }

        List<DepartmentListResponse> parentList = sourceLists.stream().filter(departmentResponse ->
                current.getParentId().equals(departmentResponse.getId())).collect(toList());

        if (CollectionUtils.isEmpty(parentList)) {
            SDepartmentDo sDepartmentDo = departmentMapper.selectById(current.getParentId());
            if (null == sDepartmentDo || FlagEnum.DELETE.getCode().equals(sDepartmentDo.getFlag())) {
                return departmentDoe;
            }
            departmentDoe = DozerUtil.map(sDepartmentDo, DepartmentListResponse.class);
            departmentDoe.setSubList(Lists.newArrayList(current));
        } else {
            departmentDoe = parentList.get(0);
            List<DepartmentListResponse> subList = new ArrayList<>();
            subList.add(current);
            departmentDoe.setSubList(subList);
        }
        departmentDoe.setNumber(countDepartmentUser(departmentDoe.getId()));
        return departmentDoe;
    }

}